package cn.edu.scau.disk.service.impl;

import cn.edu.scau.disk.exception.CommonException;
import cn.edu.scau.disk.mapper.DiskMapper;
import cn.edu.scau.disk.mapper.UserMapper;
import cn.edu.scau.disk.pojo.*;
import cn.edu.scau.disk.service.DiskService;
import cn.edu.scau.disk.service.FileService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.poi.util.ArrayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class FileServiceimpl implements FileService {


    private static final int DISK_SIZE = 128;//128个磁盘块
    private static Diretory Root = new Diretory();//根目录
    private static Map<Integer, Diretory> IdToFile = new HashMap<>();//Id（磁盘起始快）到目录引用的映射
    private boolean initflag = false;
    @Autowired
    DiskMapper diskMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    DiskService diskService;

    //生成文件树
    void FormRoot(Diretory root, Integer id) {
        root.setId(id);
        IdToFile.put(id, root);
        //找到当前目录对应的磁盘块 并抽取其磁盘阵列（数组）
        Disk disk = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", id));
        byte[] disk_value = disk.getValue();

        //遍历这个磁盘块 当遇到第一个$时表示结束符 则停止扫描
        for (int entry = 0; entry < 8; entry++) {
            if (disk_value[entry * 8] != (byte) '$') {

                //不是终结符 说明这8个字节都是目录项 拿就分别按3 2 1 1 1去提取其中的信息
                root.getDiretoryEntries()[entry] = new DiretoryEntry();
                //从磁盘读取信息 生成该目录的目录项
                //3个名字
                root.getDiretoryEntries()[entry].setName(Arrays.copyOfRange(disk_value, entry * 8, entry * 8 + 3));
                //2个类型
                root.getDiretoryEntries()[entry].setType(Arrays.copyOfRange(disk_value, entry * 8 + 3, entry * 8 + 5));
                //1个属性，也就是父节点
                root.getDiretoryEntries()[entry].setAttribute(disk_value[entry * 8 + 5]);
                //1个起始盘块 也就是文件的id
                root.getDiretoryEntries()[entry].setStart_disk(disk_value[entry * 8 + 6]);
                //1个文件的长度，也就是他占用了多少个盘块
                root.getDiretoryEntries()[entry].setLength(disk_value[entry * 8 + 7]);


                //如果是个目录 就递归生成子目录
                //如果是文件就什么都不干
                if ((int) (root.getDiretoryEntries()[entry].getType())[0] == 1) {
                    root.getDiretories()[entry] = new Diretory();
                    //递归生成子树
                    FormRoot(root.getDiretories()[entry], (int) root.getDiretoryEntries()[entry].getStart_disk());
                }
            }
        }
    }

    void showFAT() {
        byte[] FAT = GetFAT();
        for (int i = 0; i < 128; i++) {
            System.out.print(FAT[i] + " ");
        }
        System.out.println();
    }

    @Override
    public void DEBUG() throws CommonException {
//        System.out.println("##################################################");
//        System.out.println("--------------------------------------------------");
//        showFAT();
//        System.out.println("￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥");
//        showIdToFile();
//        System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
//        ShowLogicTree("", Root);
//        System.out.println("--------------------------------------------------");
//        System.out.println("##################################################");
    }

    @Override
    public void Delete(Integer fid, String name) throws CommonException {
        try {
            if (!IdToFile.containsKey(fid)) throw new CommonException("找不到父目录");
            Diretory father = IdToFile.get(fid);
            for (DiretoryEntry entry : father.getDiretoryEntries()) {
                if (entry == null) continue;
                if (new String(entry.getName()).equals(name)) {

                    if (entry.getType()[0] == 0) DeleteFile(fid, name);
                    else {
                        DeleteDir(fid, (int) entry.getStart_disk());
                    }

                    for (int i = 0; i < 8; i++) {
                        DiretoryEntry entry1 = Root.getDiretoryEntries()[i];
                        CountAllDirEryLength(Root, entry1, i);
                    }
                    return;
                }
            }
            throw new CommonException("找不到文件");
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public File Showfileinfo(Integer fid, String name) throws CommonException {
        try {
            if (!IdToFile.containsKey(fid)) throw new CommonException("找不到父目录");
            Diretory father = IdToFile.get(fid);
            for (DiretoryEntry entry : father.getDiretoryEntries()) {
                if (entry == null) continue;
                if (new String(entry.getName()).equals(name)) {
                    File file = new File();
                    file.setName(new String(entry.getName()));
                    file.setId((int) entry.getStart_disk());
                    file.setLength((int) entry.getLength());
                    file.setType((int) entry.getType()[0]);
                    file.setUserId((int) entry.getType()[1]);
                    file.setParentId((int) entry.getAttribute());
                    file.setUsername(userMapper.selectOne(new QueryWrapper<User>().eq("id", entry.getType()[1])).getUsername());
                    return file;
                }
            }
            throw new CommonException("找不到文件");
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    List<Integer> ShowdiskList_File(Integer start){

        List<Integer> diskList=new ArrayList<>();
        byte[] FAT = GetFAT();
        int now=start;
        while (now != -1) {
            diskList.add(now);
            now = FAT[now];
        }
        return diskList;
    }
    List<Integer> ShowdiskList_Dir(Integer start) throws CommonException {
        if (!IdToFile.containsKey(start)) throw new CommonException("找不到目录");
        Diretory diretory=IdToFile.get(start);
        List<Integer> disks=new ArrayList<>();
        disks.add(start);
        for (int i=0;i<8;i++){
            DiretoryEntry entry=diretory.getDiretoryEntries()[i];
            if (entry==null) continue;
            if (entry.getType()[0]==0){
                disks.addAll(ShowdiskList_File((int) entry.getStart_disk()));
            }
            else {
                disks.addAll(ShowdiskList_Dir((int) entry.getStart_disk()));
            }
        }
        return disks;
    }
    @Override
    public List<Integer> ShowdiskList(Integer fid, String name) throws CommonException {
        try {
            if (!IdToFile.containsKey(fid)) throw new CommonException("找不到父目录");
            Diretory father = IdToFile.get(fid);
            List<Integer> diskList = new ArrayList<>();
            for (DiretoryEntry entry : father.getDiretoryEntries()) {
                if (entry == null) continue;
                if (new String(entry.getName()).equals(name)) {
                    if (entry.getType()[0]==0) {
                        return ShowdiskList_File((int) entry.getStart_disk());
                    }
                    else {
                        return ShowdiskList_Dir((int) entry.getStart_disk());
                    }
                }
            }
            throw new CommonException("找不到文件");
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * FAT表的格式化：
     * 把0 1 2三个位置为-1 其他全为0
     */
    void InitFAT() {
        //把磁盘块2占用掉给Root根目录
        Disk disk0 = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", 0));
        Disk disk1 = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", 1));

        Arrays.fill(disk0.getValue(), (byte) 0);
        Arrays.fill(disk1.getValue(), (byte) 0);
        byte[] disk0_value = disk0.getValue();
        disk0_value[0] = -1;
        disk0_value[1] = -1;
        disk0_value[2] = -1;
        disk0.setValue(disk0_value);
        diskMapper.updateById(disk0);
        diskMapper.updateById(disk1);
    }

    //为新创建的目录分配磁盘块 参数只取0或1
    Integer Allocate(int disk_count) throws CommonException {
        //如果是文件的话就不分配 等写的时候再分配
        if (disk_count == 0) return -1;
        else {
            //获取FAT表 也就是前两个磁盘块
            byte[] FAT = GetFAT();
            for (int i = 3; i < 128; i++) {
                if (FAT[i] == 0) {
                    FAT[i] = -1;
                    WriteFAT(FAT);
                    return i;
                }
            }
            throw new CommonException("磁盘空间不足 无法分配");
        }
    }

    //把一个整数转成某个长度（小于等于4）的byte数组
    byte[] intToByteArray(int number, int len) {
        byte[] b = new byte[len];
        int temp = number;

        for (int i = 0; i < b.length; i++) {
            b[i] = new Integer(temp & 0xff).byteValue();
            temp = temp >> 8;
        }
        return b;

    }

    //把一个目录项对象转化为一个字节数组
    byte[] entryToByteArray(DiretoryEntry entry) {
        byte[] b = new byte[8];
        for (int i = 0; i < 3; i++) {
            b[i] = entry.getName()[i];
        }
        for (int i = 3; i < 5; i++) b[i] = entry.getType()[i - 3];
        b[5] = entry.getAttribute();
        b[6] = entry.getStart_disk();
        b[7] = entry.getLength();
        return b;
    }

    //重载 再某个磁盘块写入一个目录项 如果这个目录项记录的文件类型是目录则创建一个目录
    void CreateFile(Integer id, DiretoryEntry entry) throws CommonException {
        if (!IdToFile.containsKey(id)) {
            throw new CommonException("发送的文件id有错 无法找到对应的文件");
        }

        Diretory diretory = IdToFile.get(id);

        //再目录的目录项数组中找到第一个为null的空位 插入这个目录项 如果要插入的目录项对应的文件是个目录
        //则继续初始化这个目录
        for (int i = 0; i < 8; i++) {
            if (diretory.getDiretoryEntries()[i] == null) {
                diretory.getDiretoryEntries()[i] = entry;
                if (entry.getType()[0] == 1) {
                    diretory.getDiretories()[i] = new Diretory();
                    diretory.setParentId(id);
                    diretory.getDiretories()[i].setId((int) entry.getStart_disk());
                    IdToFile.put((int) entry.getStart_disk(), diretory.getDiretories()[i]);
                }
                break;
            }
        }

        //把目录项的内容追加到要添加的目录的磁盘块中
        boolean oom = true;
        Disk disk = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", id));
        byte[] add_value = entryToByteArray(entry);
        for (int i = 0; i < 64; i++) {
            if (disk.getValue()[i] == '$') {
                oom = false;
                for (int j = 0; j < 8; j++) {
                    disk.getValue()[i + j] = add_value[j];
                }
                //追加完后再最后加上结束符
                break;
            }
        }

        if (oom) {
            throw new CommonException("无法向目录写入文件 目录已满");
        }
        diskMapper.updateById(disk);

    }

    void showIdToFile() {
        for (Map.Entry entry : IdToFile.entrySet()) {
            System.out.println("### " + entry.getKey() + "--------------->" + entry.getValue() + " ###");
        }
    }

    /**
     * 格式化磁盘
     */
    public void FormatAll() {
        InitFAT();//初始化FAT
        for (int i = 2; i < 128; i++) {
            Disk disk = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", i));
            Arrays.fill(disk.getValue(), (byte) 0);
//            disk.getValue()[0]='';
            for (int j = 0; j < 8; j++) {
                disk.getValue()[j * 8] = '$';
            }
            diskMapper.updateById(disk);
        }
        Root = new Diretory();
        Root.setId(2);
        Root.setDiretories(new Diretory[8]);
        Root.setDiretoryEntries(new DiretoryEntry[8]);
        IdToFile = new HashMap<>();
        IdToFile.put(2, Root);
    }


    //在内存中构建逻辑文件系统
    @Override
    public void FormFileSystem() throws CommonException {
//        FormatAll();
        if (!initflag) {
            Root.setParentId(-1);
            FormRoot(Root, 2);//生成文件树
//            DEBUG();
            initflag = true;
        }
    }

    //查看新建的文件的名字是否在父目录中重名
    boolean CheckDuplicateFile(Integer id, String name) throws CommonException {
        if (!IdToFile.containsKey(id)) throw new CommonException("找不到目录");
        Diretory diretory = IdToFile.get(id);
        for (DiretoryEntry entry : diretory.getDiretoryEntries()) {
            if (entry == null) continue;
            if (new String(entry.getName()).equals(name)) {
                System.err.println(entry.getStart_disk()+" dup ");
                return true;
            }
        }
        return false;
    }


    /**
     * 展示逻辑文件树
     */
    void ShowLogicTree(String gap, Diretory root) throws CommonException {
        System.out.println(gap + root.getId() + "-" + root.getName() + " (this is a dir):");
        for (int i = 0; i < root.getDiretoryEntries().length; i++) {
            DiretoryEntry entry = root.getDiretoryEntries()[i];
            if (entry != null) {
                if (entry.getType()[0] == 0) {
                    System.out.println("---" + gap + new String(entry.getName()) + " (this is a file)");
                } else if (entry.getType()[0] == 1) {
                    ShowLogicTree("---" + gap, root.getDiretories()[i]);
                } else {
                    throw new CommonException("文件系统中存在未知类型的文件");
                }
            }
        }
    }

    void InitDirDisk(Integer id) {
        Disk disk = diskMapper.selectById(id);
        for (int i = 0; i < 8; i++) {
            disk.getValue()[i * 8] = '$';
        }
        diskMapper.updateById(disk);
    }

    //创建一个文件或者目录 根据父目录id 文件名称 和文件类型
    @Override
    public void CreateFile(Integer id, String name, Integer type, Integer userid) throws CommonException {
        DiretoryEntry entry = new DiretoryEntry();

        DEBUG();
        if (CheckDuplicateFile(id, name)) {
            throw new CommonException("文件重名");
        }

        int alloc = Allocate(type).byteValue();

        entry.setName(name.getBytes());
        entry.setType(new byte[2]);
        entry.getType()[0] = (byte) ((int) type);
        entry.getType()[1] = (byte) ((int) userid);
        entry.setLength(type.byteValue());
        entry.setStart_disk((byte) alloc);
        entry.setAttribute(id.byteValue());

        if (entry.getType()[0] != 0 && entry.getType()[0] != 1) throw new CommonException("未知文件类型");
        CreateFile(id, entry);
        if (type == 1) {
//            InitDirDisk(alloc);
        }
        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry1 = Root.getDiretoryEntries()[i];
            CountAllDirEryLength(Root, entry1, i);
        }
    }

    byte[] GetFAT() {
        List<Integer> list = new ArrayList<>();
        list.add(0);
        list.add(1);
        List<Disk> disks = diskMapper.selectBatchIds(list);
        byte[] FAT = ArrayUtils.addAll(disks.get(0).getValue(), disks.get(1).getValue());
        return FAT;
    }

    void WriteFAT(byte[] FAT) {
        byte[] disk0 = Arrays.copyOfRange(FAT, 0, 64);
        byte[] disk1 = Arrays.copyOfRange(FAT, 64, 128);
        Disk d0 = new Disk(0, disk0);
        Disk d1 = new Disk(1, disk1);
        List<Disk> disks = new ArrayList<>();
        disks.add(d0);
        disks.add(d1);
        diskService.updateBatchById(disks);
    }

    List<Integer> CompareTotalDiskSize(Integer len) {

//        System.err.println(len);
        byte[] FAT = GetFAT();
        List<Integer> disk_order = new ArrayList<>();
        int avi = 0;
        for (byte b : FAT) {
            if (b == 0) avi++;
        }

//        System.err.println(avi+" "+len);
        if (avi * 64 < len) return null;

        int disk_need = (int) Math.ceil(len * 1.0 / 64);
        int pre = -1;
        for (int i = 0; i < 128; i++) {
            if (disk_need == 0) break;
            if (FAT[i] == 0) {
                disk_need--;
                disk_order.add(i);
                if (pre != -1) FAT[pre] = (byte) i;
                pre = i;
            }
        }
        WriteFAT(FAT);
        return disk_order;
    }

    List<Integer> CompareTotalDiskSize(Integer len, int start) throws CommonException {
        byte[] FAT = GetFAT();
        List<Integer> disk_order = new ArrayList<>();

        int disk_avi = 0;
        int disk_own = 0;
        int disk_need = 0;
        int pre = -1;
        int next = start;
        while (next != -1) {
            disk_avi++;
            disk_own++;
            disk_order.add(next);
            pre = next;
            next = FAT[next];
        }

        for (int i = 0; i < 128; i++) {
            if (FAT[i] == 0) disk_avi++;
        }
        if (disk_avi * 64 < len) return null;

        disk_need = (int) Math.ceil(len * 1.0 / 64) - disk_own;

        for (int i = 0; i < 128; i++) {
            if (disk_need <= 0) break;
            if (FAT[i] == 0) {
                disk_order.add(i);
                disk_need--;
                FAT[pre] = (byte) i;
                pre = i;
            }
        }

        WriteFAT(FAT);
        return disk_order;
    }

    List<Integer> CompareTotalDiskSize(Integer len, Integer fid, String name) throws CommonException {
        List<Integer> disk_order;
        if (!IdToFile.containsKey(fid)) throw new CommonException("父目录不存在");
        Diretory father_dir = IdToFile.get(fid);
        for (DiretoryEntry entry : father_dir.getDiretoryEntries()) {
            if (entry == null) continue;

            if (new String(entry.getName()).equals(name)) {
                //如果文件未分配空间
                if (entry.getStart_disk() == -1) {
                    disk_order = CompareTotalDiskSize(len);
                } else {
                    //如果文件已分配空间
                    disk_order = CompareTotalDiskSize(len, entry.getStart_disk());
                }

                return disk_order;
            }
        }
        return null;
    }

    void WriteFile(List<Integer> disk_order, byte[] data) {
        List<Disk> disks = diskMapper.selectBatchIds(disk_order);
        int start = 0;
        for (Disk disk : disks) {
            int end = Math.min(data.length, start + 64);
            disk.setValue(Arrays.copyOfRange(data, start, end));
            start = end;
        }
        diskService.updateBatchById(disks);
    }

    void ChangeFatherDirEntry(Integer fid, List<Integer> disk_order, String name) throws CommonException {
        /**
         *这里只改变文件的父目录对应的目录项的长度
         * 上层递归交由一个中央函数处理
         */
        Diretory father = IdToFile.get(fid);
        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry = father.getDiretoryEntries()[i];
            if (entry == null) continue;
            if (new String(entry.getName()).equals(name)) {

                entry.setLength((byte) disk_order.size());
                int start = disk_order.get(0);
                entry.setStart_disk((byte) start);

                Disk disk = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", fid));
                disk.getValue()[i * 8 + 6] = (byte) start;
                disk.getValue()[i * 8 + 7] = (byte) disk_order.size();

                diskMapper.updateById(disk);
                break;
            }
        }
    }

    int CountAllDirEryLength(Diretory father, DiretoryEntry entry, int index) {
        /**
         * 这里递归计算所有目录的目录项的磁盘块总数
         */
        if (entry == null) return 0;
        if (entry.getType()[0] == 0) return entry.getLength();
        int sum = entry.getLength();
        Diretory diretory = father.getDiretories()[index];
        for (int i = 0; i < 8; i++) {
            DiretoryEntry sonEntry = diretory.getDiretoryEntries()[i];
            sum += CountAllDirEryLength(diretory, sonEntry, i);
        }
        entry.setLength((byte) sum);
        Disk father_disk = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", father.getId()));
        father_disk.getValue()[index * 8 + 7] = (byte) sum;
        return sum;
    }

    void ChangeFAT(List<Integer> disk_order) {
        disk_order.add(-1);
        byte[] FAT = GetFAT();
//        System.err.println(disk_order+" here ");
        for (int i = 0; i < disk_order.size() - 1; i++) {
            int now = disk_order.get(i);
            int next = disk_order.get(i + 1);
            FAT[now] = (byte) next;
        }
        WriteFAT(FAT);
    }

    @Override
    public void WriteFile(Integer id, String data, String name) throws CommonException {

        if (!IdToFile.containsKey(id)) throw new CommonException("父目录不存在");
        Diretory father = IdToFile.get(id);

        for (DiretoryEntry entry : father.getDiretoryEntries()) {
            if (entry == null) continue;

            if (new String(entry.getName()).equals(name)) {
                if (entry.getType()[0] == 1) throw new CommonException("不允许直接向目录写入数据");

                byte[] bytes_data = data.getBytes();
                List<Integer> disk_order;
                if (entry.getStart_disk() == -1) disk_order = CompareTotalDiskSize(bytes_data.length);
                else disk_order = CompareTotalDiskSize(bytes_data.length, entry.getStart_disk());

                if (disk_order == null) {
                    throw new CommonException("磁盘空间不足 或无法找到该文件");
                }
                WriteFile(disk_order, bytes_data);
                ChangeFatherDirEntry(id, disk_order, name);//logic tree and disk
                ChangeFAT(disk_order);

                for (int i = 0; i < 8; i++) {
                    DiretoryEntry entry1 = Root.getDiretoryEntries()[i];
                    CountAllDirEryLength(Root, entry1, i);
                }

                return;
            }
        }


    }

    @Override
    public String ReadFile(Integer fid, String name) throws CommonException {
        if (!IdToFile.containsKey(fid)) throw new CommonException("父目录不存在");
        Diretory father = IdToFile.get(fid);
        StringBuilder content = new StringBuilder();
        for (DiretoryEntry entry : father.getDiretoryEntries()) {
            if (entry == null) continue;
            if (new String(entry.getName()).equals(name)) {
                if (entry.getType()[0] == 1) {
                    throw new CommonException("这是一个目录，无法直接读取");
                }
                if (entry.getStart_disk() == -1) {
                    return "";
                }

                int now = entry.getStart_disk();
                List<Integer> disk_order = new ArrayList<>();
                while (now != -1) {
                    byte[] FAT = GetFAT();
                    disk_order.add(now);
                    now = FAT[now];
                }
                List<Disk> disks = diskMapper.selectBatchIds(disk_order);
                for (Disk disk : disks) {
                    content.append(new String(disk.getValue()));
                }
                return content.toString().substring(0, content.lastIndexOf("@"));
            }
        }
        throw new CommonException("找不到文件");
    }

    void FlushDisk(List<Integer> ids) {
        if (ids.size() == 0) return;
        List<Disk> disks = diskMapper.selectBatchIds(ids);
        for (Disk disk : disks) {
            Arrays.fill(disk.getValue(), (byte) 0);
            for (int i = 0; i < 8; i++) {
                disk.getValue()[i * 8] = '$';
            }
        }
        diskService.updateBatchById(disks);
    }

    void FlushDisk(Integer id) {
        Disk disk = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", id));
        Arrays.fill(disk.getValue(), (byte) 0);
        disk.getValue()[0] = '$';
        diskMapper.updateById(disk);
    }

    void FlushFAT(List<Integer> disk_order) {
        byte[] FAT = GetFAT();
        for (int x : disk_order) {
            FAT[x] = 0;
        }
        WriteFAT(FAT);
    }

    @Override
    public void DeleteFile(Integer fid, String name) throws CommonException {
        if (!IdToFile.containsKey(fid)) throw new CommonException("父目录不存在");

        Diretory father = IdToFile.get(fid);

        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry = father.getDiretoryEntries()[i];
            if (entry == null) continue;

            if (new String(entry.getName()).equals(name)) {
                int now = entry.getStart_disk();
                byte[] FAT = GetFAT();
                List<Integer> disk_order = new ArrayList<>();
                while (now != -1) {
                    disk_order.add(now);
                    now = FAT[now];
                }
                FlushDisk(disk_order);
                FlushFAT(disk_order);
                EraseEntry(fid, name);
                return;
            }
        }
    }

    void EraseEntry(Integer fid, String name) throws CommonException {
        if (!IdToFile.containsKey(fid)) throw new CommonException("出错 无法找到文件的父目录");
        Diretory father = IdToFile.get(fid);
        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry = father.getDiretoryEntries()[i];
            if (entry == null) continue;
            if (new String(entry.getName()).equals(name)) {

                father.getDiretories()[i] = null;
                father.getDiretoryEntries()[i] = null;

                Disk fa_disk = diskMapper.selectById(father.getId());
                fa_disk.getValue()[i * 8] = '$';
                diskMapper.updateById(fa_disk);

                break;
            }
        }
    }

    void EraseEntry(Integer fid, Integer son_id) throws CommonException {
        if (!IdToFile.containsKey(fid)) throw new CommonException("出错 无法找到文件的父目录");
        Diretory father = IdToFile.get(fid);
        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry = father.getDiretoryEntries()[i];
            if (entry == null) continue;
            if (entry.getStart_disk() == son_id) {
                father.getDiretoryEntries()[i] = null;
                father.getDiretories()[i] = null;

                Disk fa_disk = diskMapper.selectById(father.getId());
                fa_disk.getValue()[i * 8] = '$';
                diskMapper.updateById(fa_disk);

                break;
            }
        }
    }

    @Override
    public void DeleteDir(Integer fid, Integer id) throws CommonException {
        System.err.println(fid + " " + id + " " + " del dir ");
        if (id <= 2) throw new CommonException("你没有权限删除");
        if (!IdToFile.containsKey(id)) throw new CommonException("该目录不存在");
        Diretory diretory = IdToFile.get(id);
        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry = diretory.getDiretoryEntries()[i];
            if (entry == null) continue;
            if (entry.getType()[0] == 0) {
                DeleteFile(id, new String(entry.getName()));
            } else {
                Diretory son = diretory.getDiretories()[i];
                DeleteDir(id, son.getId());
            }
        }
        List<Integer> disk_order = new ArrayList<>();
        disk_order.add(diretory.getId());
        FlushDisk(disk_order);
        FlushFAT(disk_order);

        EraseEntry(fid, id);
        IdToFile.remove(id);
    }

    @Override
    public void RenameFile(Integer fid, String oldname, String newname) throws CommonException {
        if (!IdToFile.containsKey(fid)) throw new CommonException("父目录不存在");
        if (CheckDuplicateFile(fid, newname)) throw new CommonException("文件名字重复");
        Diretory father = IdToFile.get(fid);
        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry = father.getDiretoryEntries()[i];
            if (entry == null) continue;
            if (new String(entry.getName()).equals(oldname)) {
                entry.setName(newname.getBytes());
                byte[] tmp = newname.getBytes();
                byte[] newname_bytes = new byte[3];
                for (int j = 0; j < 3; j++) {
                    if (j >= tmp.length) newname_bytes[j] = '\0';
                    else newname_bytes[j] = tmp[j];
                }
                Disk father_disk = diskMapper.selectOne(new QueryWrapper<Disk>().eq("id", fid));
                System.arraycopy(newname_bytes, 0, father_disk.getValue(), i * 8, 3);
                diskMapper.updateById(father_disk);
                return;
            }
        }
    }


    void ListFile(Diretory root, String keyword, List<File> fileList) {
        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry = root.getDiretoryEntries()[i];
            if (entry == null) continue;

            if (new String(entry.getName()).contains(keyword)) {
                File file = new File();
                file.setName(new String(entry.getName()));
                file.setId((int) entry.getStart_disk());
                file.setLength((int) entry.getLength());
                file.setType((int) entry.getType()[0]);
                file.setUserId((int) entry.getType()[1]);
                file.setParentId((int) entry.getAttribute());
                file.setUsername(userMapper.selectOne(new QueryWrapper<User>().eq("id", entry.getType()[1])).getUsername());
                fileList.add(file);
            }
            if (entry.getType()[0] == 1) {
                ListFile(root.getDiretories()[i], keyword, fileList);
            }
        }
    }

    @Override
    public List<File> ListFile(String keyword) {
        List<File> fileList = new ArrayList<>();
        ListFile(Root, keyword, fileList);
        return fileList;
    }

    public List<File> ListSingleFile(Integer id, String keyword) throws CommonException {
        if (!IdToFile.containsKey(id)) {
            throw new CommonException("父目录不存在");
        }
        Diretory father = IdToFile.get(id);
        List<File> fileList = new ArrayList<>();

        for (int i = 0; i < 8; i++) {
            DiretoryEntry entry = father.getDiretoryEntries()[i];
            if (entry == null) continue;
            if (new String(entry.getName()).contains(keyword)) {
                File file = new File();
                file.setName(new String(entry.getName()));
                file.setLength((int) entry.getLength());
                file.setType((int) entry.getType()[0]);
                file.setId((int) entry.getStart_disk());
                file.setUserId((int) entry.getType()[1]);
                file.setParentId((int) entry.getAttribute());
                file.setUsername(userMapper.selectOne(new QueryWrapper<User>().eq("id", entry.getType()[1])).getUsername());
                fileList.add(file);
            }
        }
        return fileList;
    }

    @Override
    public List<Integer> showDirDisks() {
        List<Integer> list=new ArrayList<>();
        for (Map.Entry entry:IdToFile.entrySet()){
            list.add((Integer) entry.getKey());
        }
        return list;
    }
}
